﻿/**
 * Output
 * this class is modified from Senocular's Output class
 * @author		Allen Chou
 * @version		1.0.3 (last update: Aug 29 2008)
 * @link        http://cjcat.blogspot.com
 * @link		http://cjcat2266.deviantart.com
 */

package idv.cjcat.display {
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
	import flash.text.*;
	
	/**
	 * The <code>Output</code> class lets you create an "console output panel" at the top of the Flash movie.
	 * <p>This can be used for runtime debugging or showing runtime information</p>
	 */
	public class Output extends MovieClip {
		public var autoExpand:Boolean;
		
		internal var textField:TextField;
		
		private var maxLength:int = int.MAX_VALUE;
		private var _bg:Shape;
		private var _bgColor:uint;
		private var _bgAlpha:uint;
		
		public function Output(outputWidth:uint = 640,
							   outputHeight:uint = 142,
							   autoExpand:Boolean = true,
							   backgroundColor:uint = 0x000000,
							   backgroundAlpha:Number = 0.75) {
			
			addChild(newOutputField(outputHeight));
			
			this.autoExpand = autoExpand;
			
			_bg = new Shape();
			_bg.graphics.beginFill(backgroundColor, backgroundAlpha);
			_bg.graphics.drawRect(0, 0, 100, 100);
			addChildAt(_bg, 0);
			
			width = outputWidth;
			height = outputHeight;
		}
		
		// public methods
		/**
		 * Prints a message.
		 * @param	str  The message.
		 * @return The <code>Output</code> object. This is for the purpose of method concatenation, as in:
		 * <listing>
		 * output.print("Hello ").print("world!");</listing>
		 */
		public function print(str:*):Output {
			this.textField.appendText(str);
			if (this.textField.length > maxLength) {
				this.textField.text = this.textField.text.slice(-maxLength);
			}
			this.textField.scrollV = this.textField.maxScrollV;
			if (autoExpand && !this.textField.visible) this.show();
			
			return this;
		}
		
		/**
		 * Prints a message and moves the cursor to the next line.
		 * @param	str  The message.
		 * @return The <code>Output</code> object. This is for the purpose of method concatenation, as in:
		 * <listing>
		 * output.println("First line.").println("Second line.").println("Third line.");</listing>
		 */
		public function println(str:*):Output {
			return print(str + "\n");
		}
		
		/**
		 * Moves the cursor to the next line.
		 * @return The <code>Output</code> object. This is for the purpose of method concatenation, as in:
		 * <listing>
		 * output.println("First line.").endl().println("Third line.");</listing>
		 */
		public function endl():Output {
			return print("\n");
		}
		
		/**
		 * Clears the text in the output panel.
		 * @return The <code>Output</code> object. This is for the purpose of method concatenation, as in:
		 * <listing>
		 * output.println("Old text.").clear().println("New text.");</listing>
		 */
		public function clear():Output {
			this.textField.text = "";
			return this;
		}
		
		/**
		 * Expand the output panel.
		 */
		public function show():void {
			if (!textField.visible) _bg.visible = textField.visible = true;
		}
		
		/**
		 * Collapses/Hides the output panel.
		 */
		public function hide():void {
			if (textField.visible) _bg.visible = textField.visible = false;
		}
		
		/**
		 * Toggle the output panel between expanded and collapsed states.
		 */
		public function toggle():void {
			_bg.visible = textField.visible = !textField.visible;
		}
		
		/**
		 * Returns the text format of the output panel.
		 * @return The text format.
		 */
		public function getTextFormat():TextFormat {
			return textField.getTextFormat();
		}
		
		/**
		 * Sets the text format of the output panel.
		 * @param	value  The text format.
		 */
		public function setTextFormat(value:TextFormat):void {
			textField.setTextFormat(value);
			textField.defaultTextFormat = value;
		}
		
		/**
		 * The background color of the output panel.
		 */
		public function get backgroundColor():uint { return _bgColor; }
		public function set backgroundColor(value:uint):void {
			_bgColor = value;
			_bg.graphics.clear();
			_bg.graphics.beginFill(_bgColor, _bgAlpha);
			_bg.graphics.drawRect(0, 0, 100, 100);
			this.width = this.width;
			this.height = this.height;
		}
		
		/**
		 * The background alpha of the output panel.
		 */
		public function get backgroundAlpha():uint { return _bgAlpha; }
		public function set backgroundAlpha(value:uint):void {
			_bgAlpha = value;
			_bg.graphics.clear();
			_bg.graphics.beginFill(_bgColor, _bgAlpha);
			_bg.graphics.drawRect(0, 0, 100, 100);
			this.width = this.width;
			this.height = this.height;
		}
		
		/**
		 * The width of the output panel.
		 */
		override public function get width():Number { return super.width; }
		override public function set width(value:Number):void {
			textField.width = value;
			_bg.width = value;
		}
		
		/**
		 * The height of the output panel.
		 */
		override public function get height():Number { return super.height; }
		override public function set height(value:Number):void {
			textField.height = value;
			_bg.height = value;
		}
		
		/**
		 * Whether the text in the output panel is selectable.
		 */
		public function get selectable():Boolean { return textField.selectable; }
		public function set selectable(value:Boolean):void { textField.selectable = value; }
		
		//private methods
		private function newOutputField(outputHeight:uint):TextField {
			textField = new TextField();
			textField.textColor = 0xFFFFFF;
			textField.type = TextFieldType.DYNAMIC;
			textField.selectable = false;
			textField.height = outputHeight;
			var format:TextFormat = textField.getTextFormat();
			format.font = "_typewriter";
			textField.setTextFormat(format);
			textField.defaultTextFormat = format;
			return textField;
		}
		
	}
}